(ns clj-gallery.routes.auth
  (:require [clojure.java.io :as io]
            [clojure.java.jdbc :as sql]
            [hiccup.form :refer :all]
            [compojure.core :refer :all]
            [noir.session :as session]
            [noir.response :as resp]
            [noir.validation :as vali]
            [noir.util.crypt :as crypt]
            [noir.util.route :refer [restricted]]

            [clj-gallery.models.db :as db]
            [clj-gallery.routes.home :refer :all]
            [clj-gallery.util :refer [gallery-path login-user-id]]
            [clj-gallery.views.layout :as layout]
            [clj-gallery.routes.upload :as upload]
            )
  (:import (java.io File)
           (java.sql SQLException)))

#_(defn delete-account-page []
    (layout/common
      (form-to [:post "/confirm-delete"]
               (submit-button "delete account"))
      (form-to [:get "/"]
               (submit-button "cancel"))))

(defn delete-account-page []
  (layout/render "delete_account.html"))

(defn handle-confirm-delete []
  (let [userid (login-user-id)]
    (doseq [{:keys [name]} (db/images-by-user userid)]
      (upload/delete-image userid name))
    (doseq [file (-> (gallery-path) io/file file-seq reverse)]
      (io/delete-file file))
    (db/delete-user userid))
  (session/clear!)
  (resp/redirect "/"))

(defn create-gallery-path []
  (let [user-path (io/file (gallery-path))]
    (when-not (.exists user-path)
      (.mkdirs user-path))
    (str (.getAbsolutePath user-path) File/separator)))

(defn valid? [id pass pass1]
  (vali/rule (vali/has-value? id)
             [:id "user id is required"])
  (vali/rule (vali/min-length? pass 5)
             [:pass "password must be at least 5 characters"])
  (vali/rule (= pass pass1)
             [:pass "entered passwords do not match"])
  (not (vali/errors? :id :pass :pass1)))

(defn error-item [[error]]
  [:div.error error])

(defn control [id label field]
  (list
    (vali/on-error id error-item)
    label
    field
    [:br]))

#_(defn registration-page [& [id]]
    (layout/base
      (form-to [:post "/register"]

               (control :id
                        (label "user-id" "user id")
                        (text-field {:tabindex 1} "id" id))

               (control :pass
                        (label "pass" "password")
                        (password-field {:tabindex 2} "pass"))

               (control :pass1
                        (label "pass1" "retype password")
                        (password-field {:tabindex 3} "pass1"))

               (submit-button {:tabindex 4} "create account"))))

(defn registration-page [& [id]]
  (layout/render "registration.html" {:id         id
                                      :id-error   (first (vali/get-errors :id))
                                      :pass-error (first (vali/get-errors :pass))}))

(defn format-error [id ex]
  (cond
    (and (instance? SQLException ex) (= 0 (.getErrorCode ex)))
    (str "The user with id " id " already exists!")

    :else
    (str "An error has occured while processing the request: ")))

(defn handle-registration [id pass pass1]
  (if (valid? id pass pass1)
    (try
      (db/create-user {:id id :pass (crypt/encrypt pass)})
      (session/put! :user id)
      (resp/redirect "/")
      (catch Exception ex
        (vali/rule false [:id (format-error id ex)])
        (registration-page)))
    (registration-page id)))

(defn handle-login [id pass]
  (let [user (db/get-user id)]
    (when (and user (crypt/compare pass (:pass user)))
      (session/put! :user id)))
  (resp/redirect "/"))

(defn handle-logout []
  (session/clear!)
  (resp/redirect "/"))

(defroutes auth-routes
  (GET "/register" []
    (registration-page))

  (POST "/register" [id pass pass1]
    (handle-registration id pass pass1))

  (POST "/login" [id pass]
    (handle-login id pass))

  (ANY "/logout" []
    (handle-logout))

  (GET "/delete-account" []
    (restricted (delete-account-page)))

  (POST "/confirm-delete" []
    (restricted (handle-confirm-delete))))